/*********************
* Author:Dzlua
* QQ:505544956
* time:2016/11/28
*/
#include "LuaHelper.h"

#ifdef EDUI_USE_LUAPLUS

#include "LuaEngine.h"
#include "LuaFont.h"
#include "LuaCursor.h"
#include "LuaSurface.h"
#include "LuaAnimation.h"
#include "LuaWindow.h"
#include "controls/LuaControl.h"
#include "controls/LuaLabel.h"
#include "controls/LuaLink.h"
#include "controls/LuaText.h"
#include "controls/LuaEdit.h"
#include "controls/LuaButton.h"
#include "controls/LuaCheckBox.h"
#include "controls/LuaProgress.h"
#include "controls/LuaSlider.h"
#include "controls/LuaScrollBar.h"
#include "container/LuaContainer.h"
#include "container/LuaHorizontalLayout.h"
#include "container/LuaVerticalLayout.h"
#include "container/LuaTableLayout.h"
#include "container/LuaTileLayout.h"

#include "base/LuaBase.h"

#include <string>

EDUI_NAMESPACE_BEGIN

namespace {
    std::string key_to_string(void *key) {
        std::string idx;
        idx = std::to_string((uint64_t)key);
        return std::move(idx);
    }
} // end namespace

namespace LuaHelper{

void RegisterLuaAll(LuaState *L)
{
    LuaObject ns = L->GetGlobals().CreateTable("EDUI");
    //save Luaclass metatable
    ns.CreateTable("__edui_metatables__");
    //save Luaclass objects
    ns.CreateTable("__edUI_objects__");
    //Register lua base
    LuaBase::RegisterLuaBaseAll(L);

    LuaEngine::Register(L);
    LuaFont::Register(L);
    LuaSurface::Register(L);
    LuaCursor::Register(L);
    LuaAnimation::Register(L);
    LuaWindow::Register(L);
    LuaControl::Register(L);
    LuaLabel::Register(L);
    LuaLink::Register(L);
    LuaText::Register(L);
    LuaEdit::Register(L);
    LuaButton::Register(L);
    LuaCheckBox::Register(L);
    LuaProgress::Register(L);
    LuaSlider::Register(L);
    LuaScrollBar::Register(L);
    LuaContainer::Register(L);
    LuaHorizontalLayout::Register(L);
    LuaVerticalLayout::Register(L);
    LuaTableLayout::Register(L);
    LuaTileLayout::Register(L);

}

//get the table where save Luaclass metatable
LuaObject GetTableOfMetas(LuaState *L)
{
    return L->GetGlobal("EDUI")["__edui_metatables__"];
}

//get the table where save Luaclass objects
LuaObject GetTableOfObjs(LuaState *L)
{
    return L->GetGlobal("EDUI")["__edUI_objects__"];
}

//create a table to saved Luaclass metatables.return the table.
LuaObject AddToMetas(LuaState *L, const char* key, const char* parent)
{
    LuaObject obj = GetTableOfMetas(L).CreateTable(key);
    if (parent){
        obj.SetMetatable(GetFromMetas(L, parent));
    }
    return obj;
}

//add the table from save Luaclass metatables
LuaObject GetFromMetas(LuaState *L, const char* key)
{
    return GetTableOfMetas(L)[key];
}

//remove the table from save Luaclass metatables
void RemoveFromMetas(LuaState *L, const char* key)
{
    GetTableOfMetas(L).SetNil(key);
}

//create a table to saved Luaclass objects.return the table.
LuaObject AddToObjs(LuaState *L, void* key)
{
    std::string idx = key_to_string(key);
    return GetTableOfObjs(L).CreateTable(idx.c_str());
}

//get the table from save Luaclass objects
LuaObject GetFromObjs(LuaState *L, void* key)
{
    std::string idx = key_to_string(key);
    return GetTableOfObjs(L)[idx.c_str()];
}

//remove the table from save Luaclass objects
void RemoveFromObjs(LuaState *L, void* key)
{
    std::string idx = key_to_string(key);
    GetTableOfObjs(L).SetNil(idx.c_str());
}

//add a event to Objs
bool SetEventToObjs(LuaState *L, void* key, const char* evtname, LuaObject event)
{
    if (!evtname || !event.IsFunction()) return false;
    LuaObject obj = GetFromObjs(L, key);
    if (obj.IsNil()) return false;
    if (obj["__events__"].IsNil()) obj.CreateTable("__events__");
    obj["__events__"].SetObject(evtname, event);
    return true;
}

//get a event from Objs
LuaObject GetEventFromObjs(LuaState *L, void* key, const char* eventname)
{
    LuaObject obj = GetFromObjs(L, key);
    if (obj.IsNil()) return obj;
    obj = obj["__events__"];
    if (obj.IsNil()) return obj;
    return obj[eventname];
}

//remove the event from Objs
void RemoveEventFromObjs(LuaState *L, void* key, const char* eventname)
{
    LuaObject obj = GetFromObjs(L, key);
    if (obj.IsNil()) return;
    obj = obj["__events__"];
    if (obj.IsNil()) return;
    obj.SetNil(eventname);
}

//add a timer to Objs
bool SetTimerToObjs(LuaState *L, void* key, TimerID id, LuaObject callback)
{
    if (!callback.IsFunction()) return false;
    LuaObject obj = GetFromObjs(L, key);
    if (obj.IsNil()) return false;
    if (obj["__timers__"].IsNil()) obj.CreateTable("__timers__");
    obj["__timers__"].SetObject(id, callback);
    return true;
}

//get a timer from Objs
LuaObject GetTimerFromObjs(LuaState *L, void* key, TimerID id)
{
    LuaObject obj = GetFromObjs(L, key);
    if (obj.IsNil()) return obj;
    obj = obj["__timers__"];
    if (obj.IsNil()) return obj;
    return obj[id];
}

//remove the timer from Objs
void RemoveTimerFromObjs(LuaState *L, void* key, TimerID id)
{
    LuaObject obj = GetFromObjs(L, key);
    if (obj.IsNil()) return;
    obj = obj["__timers__"];
    if (obj.IsNil()) return;
    obj.SetNil(id);
}

//set a c++ pointer to table.
void SetCObject(LuaObject obj, LuaClassBase* cobj)
{
    obj.SetLightUserdata("__object", cobj);
}

//get the c++ pointer if had.
LuaClassBase* GetCObject(LuaObject obj)
{
    if (!obj.IsTable()) return 0;
    return (LuaClassBase*)obj["__object"].GetLightUserdata();
}

//get the c++ pointer's data
void* GetCObjectData(LuaObject obj)
{
    LuaClassBase* pCObj = GetCObject(obj);
    if (!pCObj) return 0;
    return pCObj->GetCObj();
}

}
EDUI_NAMESPACE_END

#endif